/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package de.tor.tribes.types;

import de.tor.tribes.reportserver.PersistenceImpl;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;

/**
 *
 * @author Torridity
 */
@Entity
@Table(name = "UserGroups")
public class ZebraGroup implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @OneToMany(mappedBy = "userGroup", cascade = CascadeType.ALL)
    private Set<ZebraGroupMembership> memberships;

    public ZebraGroup() {
        memberships = new HashSet<ZebraGroupMembership>();
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public boolean addMember(final ZebraUser pMember, PersistenceImpl pPersistence) {
        if (memberships == null) {
            memberships = new HashSet<ZebraGroupMembership>();
        }

        ZebraGroupMembership m = findMembership(pMember);
        if (m == null) {
            m = new ZebraGroupMembership();
            m.setReportUser(pMember);
            m.setUserGroup(this);
            m.setRole(ZebraRole.MEMBER);
            memberships.add(m);
            pPersistence.persistUserGroup(this);
            pPersistence.reloadUser(pMember);
            return true;
        }
        return false;
    }

    private ZebraGroupMembership findMembership(final ZebraUser pMember) {
        return (ZebraGroupMembership) CollectionUtils.find(memberships, new Predicate() {
            public boolean evaluate(Object o) {
                ZebraGroupMembership m = (ZebraGroupMembership) o;
                return m.getReportUser().equals(pMember);
            }
        });
    }

    public boolean isAdmin(ZebraUser pUser) {
        ZebraGroupMembership membership = findMembership(pUser);
        if (membership != null) {
            return membership.getRole().equals(ZebraRole.ADMIN);
        }
        return false;
    }

    public boolean isPrivileged(ZebraUser pUser) {
        ZebraGroupMembership membership = findMembership(pUser);
        if (membership != null) {
            return !membership.getRole().equals(ZebraRole.MEMBER);
        }
        return false;
    }

    public void addAdmin(final ZebraUser pMember, PersistenceImpl pPersistence) {
        if (memberships == null) {
            memberships = new HashSet<ZebraGroupMembership>();
        }
        ZebraGroupMembership m = findMembership(pMember);
        if (m == null) {
            m = new ZebraGroupMembership();
            m.setReportUser(pMember);
            m.setUserGroup(this);
            m.setRole(ZebraRole.ADMIN);
            m.setAccepted(true);
            memberships.add(m);
        } else {
            m.setRole(ZebraRole.ADMIN);
            m.setAccepted(true);
        }
        pPersistence.persistUserGroup(this);
        pPersistence.reloadUser(pMember);
    }

    public boolean grantRole(ZebraUser pMember, ZebraRole pRole, PersistenceImpl pPersistence) {
        ZebraGroupMembership m = findMembership(pMember);
        if (m != null) {
            if (m.getRole().equals(pRole)) {
                return false;
            }
            m.setRole(pRole);
            pPersistence.persistUserGroup(this);
            pPersistence.reloadUser(pMember);
            return true;
        }
        return false;
    }

    public void removeUser(final ZebraUser pMember, PersistenceImpl pPersistence) {
        if (memberships == null) {
            memberships = new HashSet<ZebraGroupMembership>();
        }
        ZebraGroupMembership m = findMembership(pMember);
        if (m != null) {
            memberships.remove(m);
            pPersistence.persistUserGroup(this);
        }
    }

    public boolean isLastAdmin(final ZebraUser pUser) {
        ZebraGroupMembership membership = findMembership(pUser);
        if (!membership.getRole().equals(ZebraRole.ADMIN)) {
            return false;
        }
        int admins = CollectionUtils.countMatches(memberships, new Predicate() {
            public boolean evaluate(Object o) {
                ZebraGroupMembership m = (ZebraGroupMembership) o;
                return m.getRole().equals(ZebraRole.ADMIN);
            }
        });

        return admins == 1;
    }

    @Override
    public String toString() {
        return getName();
    }

    protected void removeMembership(ZebraGroupMembership pMembership) {
        memberships.remove(pMembership);
    }

    public ZebraGroupMembership[] getMemberships() {
        return getMemberships(false);
    }

    public ZebraGroupMembership[] getMemberships(boolean pSort) {
        ZebraGroupMembership[] result = memberships.toArray(new ZebraGroupMembership[memberships.size()]);
        if (pSort) {
            Arrays.sort(result, ZebraGroupMembership.MEMBERSHIP_ROLE_COMPARATOR);
        }
        return result;
    }

    public void delete(PersistenceImpl pPersistence) {
        for (ZebraGroupMembership m : memberships.toArray(new ZebraGroupMembership[]{})) {
            m.getReportUser().leaveGroup(this, pPersistence);
        }
        pPersistence.removeUserGroup(this);
    }
}
